package tcpserver.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import tcpserver.config.TcpServerConfig;
import tcpserver.handler.TcpServerHandler;
import tcpserver.handler.TcpServerHandler;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.TimeUnit;

/**
 * 基于Netty的TCP服务器
 * 
 * 提供高性能的TCP通信服务，支持多客户端连接
 */
@Component
public class NettyTcpServer {
    
    private static final Logger logger = LoggerFactory.getLogger(NettyTcpServer.class);
    
    @Autowired
    @Qualifier("tcpServerConfig")
    private TcpServerConfig config;
    
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private Channel serverChannel;
    
    private volatile boolean isRunning = false;
    
    /**
     * 启动TCP服务器
     */
    @PostConstruct
    public void start() {
        if (isRunning) {
            logger.warn("TCP服务器已经在运行中");
            return;
        }
        
        try {
            logger.info("正在启动TCP服务器...");
            logger.info("服务器配置: {}", config);
            
            // 创建事件循环组
            bossGroup = new NioEventLoopGroup(config.getBossThreads());
            
            int workerThreads = config.getWorkerThreads();
            if (workerThreads <= 0) {
                workerThreads = Runtime.getRuntime().availableProcessors() * 2;
            }
            workerGroup = new NioEventLoopGroup(workerThreads);
            
            // 创建服务器启动器
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, config.getBacklog())
                    .option(ChannelOption.SO_REUSEADDR, config.isReuseAddr())
                    .childOption(ChannelOption.TCP_NODELAY, config.isTcpNodelay())
                    .childOption(ChannelOption.SO_KEEPALIVE, config.isKeepAlive())
                    .childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, config.getConnectTimeout())
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            
                            // 添加空闲状态处理器
                            pipeline.addLast("idleStateHandler", new IdleStateHandler(
                                    config.getReaderIdleTime(),
                                    config.getWriterIdleTime(),
                                    config.getAllIdleTime(),
                                    TimeUnit.SECONDS));
                            
                            // 添加日志处理器（可选）
                            // pipeline.addLast("logging", new LoggingHandler(LogLevel.DEBUG));
                            
                            // 添加自定义消息处理器（每个连接独立实例）
                            pipeline.addLast("serverHandler", new TcpServerHandler());
                        }
                    });
            
            // 绑定端口并启动服务器
            ChannelFuture future = bootstrap.bind(config.getHost(), config.getPort()).sync();
            
            if (future.isSuccess()) {
                serverChannel = future.channel();
                isRunning = true;
                
                logger.info("TCP服务器启动成功！");
                logger.info("服务器地址: {}:{}", config.getHost(), config.getPort());
                logger.info("Boss线程数: {}", config.getBossThreads());
                logger.info("Worker线程数: {}", workerThreads);
                
                // 启动状态监控线程
                startStatusMonitor();
                
            } else {
                logger.error("TCP服务器启动失败");
                shutdown();
            }
            
        } catch (Exception e) {
            logger.error("启动TCP服务器时发生错误", e);
            shutdown();
        }
    }
    
    /**
     * 关闭TCP服务器
     */
    @PreDestroy
    public void shutdown() {
        if (!isRunning) {
            return;
        }
        
        logger.info("正在关闭TCP服务器...");
        
        try {
            isRunning = false;
            
            // 关闭服务器通道
            if (serverChannel != null) {
                serverChannel.close().sync();
            }
            
            // 优雅关闭事件循环组
            if (workerGroup != null) {
                workerGroup.shutdownGracefully(2, 10, TimeUnit.SECONDS);
            }
            if (bossGroup != null) {
                bossGroup.shutdownGracefully(2, 10, TimeUnit.SECONDS);
            }
            
            logger.info("TCP服务器已关闭");
            
        } catch (InterruptedException e) {
            logger.error("关闭TCP服务器时发生错误", e);
            Thread.currentThread().interrupt();
        }
    }
    
    /**
     * 启动状态监控线程
     */
    private void startStatusMonitor() {
        Thread monitorThread = new Thread(() -> {
            while (isRunning) {
                try {
                    Thread.sleep(30000); // 每30秒输出一次状态
                    
                    if (isRunning) {
                        logger.info("TCP服务器状态 - 运行中 | 当前连接数: {} | 端口: {}", 
                                  TcpServerHandler.getCurrentConnectionCount(), 
                                  config.getPort());
                    }
                    
                } catch (InterruptedException e) {
                    logger.debug("状态监控线程被中断");
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    logger.error("状态监控异常", e);
                }
            }
        });
        
        monitorThread.setName("TCP-Server-Monitor");
        monitorThread.setDaemon(true);
        monitorThread.start();
    }
    
    /**
     * 检查服务器是否正在运行
     */
    public boolean isRunning() {
        return isRunning;
    }
    
    /**
     * 获取服务器配置
     */
    public TcpServerConfig getConfig() {
        return config;
    }
    
    /**
     * 获取当前连接数
     */
    public int getCurrentConnectionCount() {
        return TcpServerHandler.getCurrentConnectionCount();
    }
    
    /**
     * 获取服务器信息
     */
    public String getServerInfo() {
        return String.format("TCP服务器 - 地址: %s:%d | 状态: %s | 连接数: %d", 
                           config.getHost(), 
                           config.getPort(), 
                           isRunning ? "运行中" : "已停止", 
                           getCurrentConnectionCount());
    }
}